Main
2018-02-08

Awesome way to debug python

This it so awesome. The probably most foolproof method to debug python after printf-debugging:

import code
code.interact(local=dict(globals(), **locals()))

You can add this at any position in your code you like. Whenever the second line is executed the python-read-evaluate-print-loop (REPL) is started and you can interact with your program live: you can check the values of your variables and run arbitrary code. After you exit the shell, your code continues to run normally.

But it gets even better. You can use this also if you don't know where in the code the problem is occurring, you can even use it preventive before you know about bugs (but make sure to remove before shipping to customers). Add this to the to of your code:

import signal
import code

def debug_handler(signum, frame):
    code.interact(local=globals())

signal.signal(signal.SIGUSR1, debug_handler)

This will register a signal handler for the signal SIGUSR1. Your program will run completely normal but whenever you run into a bug and want to debug, simply send a corresponding signal to the process:

$ kill -SIGUSR1 <pid>

This will open a REPL and you can look at any global variables and run code — you can even modify the content of variables or rewrite whole functions! So you could try out a potential bugfix live without restarting the program.

Actually you can also edit variables and functions with the first way (without a signal) — but you have to decide if you want to have access at only the global or only the local scopes. The compounding of the globals and locals with the dict copies the values, so that you won't modify the original anymore. If you really need to access and modify local and global variables you could use a little trick:

code.interact(local={'gvar': globals(), 'lvar': locals()})

But you then have to access the variables and functions by gvar['varname'] — much less easy and elegant… In that cases you might want to switch to something more advanced like pdb anyway.

There are two additional tricks: First: You can use the parameters banner= and exitmsg= to overwrite pythons default message when starting the REPL and to show something when exiting the REPL. Second: If you have IPython installed — it has the same functionality available, so then use the following instead to get a colorful more interactive shell:

import IPython
IPython.embed()

Only downside of IPython: I haven't found a way to change variables.

Happy Hacking!

en python


Creative Commons License Awesome way to debug python by Michael F. Schönitzer is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.